<template>
  <div class="content-box button-demo">
    <h2 class="demo-title">高精度计时器</h2>
    <p class="demo-introduction">毫秒级,更加准确</p>

    <!-- 虚拟滚动 -->
    <g-block-box
      id="magnifier"
    >
      <template v-slot:demo>
        <g-timer/>
      </template>
      <template v-slot:code>
        <code class="html">{{ fCode(code) }}</code>
      </template>
    </g-block-box>
  </div>
</template>

<script>
export default {
  data() {
    return {
      code: `<template>
          <div>
            <div>
              计时：{{ date.days }}天{{ date.hours }}时{{ date.minutes }}分{{
                date.seconds
              }}秒{{ date.milliseconds }}毫秒
            </div>
            <div class="btnGroup">
              <g-button @click.native="handStart">启动</g-button>
              <g-button @click.native="handPause" type="primary">暂停</g-button>
              <g-button @click.native="handContinue">继续</g-button>
              <g-button @click.native="handReset" type="success">重置</g-button>
            </div>
          </div>
        </template>

      <script>
      // 基于requestAnimationFrame实现一个倒计时组件
      // 1.解析时间
      // 2.补上暂停的时间
      export default {
        // eslint-disable-next-line vue/multi-word-component-names
        name: 'timer',
        data() {
          return {
            date: {
              days: 0,
              hours: 0,
              minutes: 0,
              seconds: 0,
              milliseconds: 0,
            },
            dateCopy: {},
            rafId: null,
            stopTime: 0,
            startTime: 0,
            // 是否正在计时中
            isTiming: false,
          }
        },
        created() {
          this.dateCopy = this.deepClone(this.date)
        },
        methods: {
          process(time) {
            time = time - this.startTime
            const vm = this
            const resTime = vm.parseTime(time)
            Object.assign(vm.date, resTime)
            this.rafId = window.requestAnimationFrame(this.process)
          },
          /**
           * 解析时间
           * @param {*} time
           * @return {*}
           */
          parseTime(time) {
            let SECOND = 1000
            let MINUTE = SECOND * 60
            let HOUR = MINUTE * 60
            let DAY = HOUR * 24
            const milliseconds = Math.floor(time % SECOND)
            const seconds = Math.floor((time % MINUTE) / SECOND)
            const minutes = Math.floor((time % HOUR) / MINUTE)
            const hours = Math.floor((time % DAY) / HOUR)
            const days = Math.floor(time / DAY)
            return {
              total: time,
              days,
              hours,
              minutes,
              seconds,
              milliseconds,
            }
          },
          /**
           * 启动定时器
           */
          handStart() {
            if (this.isTiming) {
              return
            }
            this.startTime = performance.now()
            this.isTiming = true
            this.rafId = window.requestAnimationFrame(this.process)
          },
          /**
           * 暂停
           */
          handPause() {
            if (!this.isTiming) {
              return
            }
            this.isTiming = false
            this.stopTime = performance.now()
            if (this.rafId) {
              window.cancelAnimationFrame(this.rafId)
            }
          },
          /**
           * 继续
           */
          handContinue() {
            if (this.isTiming) {
              return
            }
            this.isTiming = true
            // 开始时间改变，等于原有的开始时间加上当前时间减去暂停时候的时间
            this.startTime += performance.now() - this.stopTime
            this.rafId = window.requestAnimationFrame(this.process)
          },
          /**
           * 重置
           */
          handReset() {
            this.handPause()
            this.date = this.deepClone(this.dateCopy)
          },
        },
      }
      <\/script>
      
      <style lang="scss" scoped>
      .btnGroup {
        margin-top: 10px;
        button {
          margin-right: 10px;
        }
      }
      </style>
      `
    }
  }
}
</script>
